package net.xxcxcxcx.xc_enhancedmob.render.boss_bar.complete;

import net.minecraft.entity.mob.MobEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;
import net.xxcxcxcx.xc_enhancedmob.packet.dirty.DataTracking;
import net.xxcxcxcx.xc_enhancedmob.render.boss_bar.column.CustomBossBarColumn;
import net.xxcxcxcx.xc_enhancedmob.render.boss_bar.unit.CustomBossBar;
import org.jetbrains.annotations.Nullable;

import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * CustomBossBarComplete的基础
 * <p>是具体一组CustomBossbarColumn的实现
 * <p>其本质上是一个水平分布的多段多条血条
 * <p>|========--------|    |=============|
 * <p>|===========---|    |========--------|
 */
public abstract class BaseCustomBossBarComplete implements CustomBossBarComplete {
    private final DataTracking<Text> name = new DataTracking<>();//生物名称
    private final DataTracking<Integer> SortCount = new DataTracking<>();//sort排序
    private final DataTracking<Boolean> showname = new DataTracking<>(false);//是否要显示名称
    private CopyOnWriteArrayList<CustomBossBarColumn> bossColumns = new CopyOnWriteArrayList();
    private boolean drity = false;//是否需要更新

    @Override
    public void writeDrityCustomDataToNbt(NbtCompound nbt) {
        for (int i = 0; i < getBossColumn().size(); i++) {
            if (!getBossColumn().get(i).getDrity()) continue;
            NbtCompound nbtCompound = new NbtCompound();
            getBossColumn().get(i).writeDrityCustomDataToNbt(nbtCompound);
            getBossColumn().get(i).setDrity(false);
            nbt.put(getBossColumn().get(i).getUuid().getValue().toString(), nbtCompound);
        }
        if (name.getValue() != null && name.isDirty()) {
            name.setDirty(false);
            nbt.putString("name", Text.Serializer.toJson(getName().getValue()));
        }
        if (getShowname().isDirty()) {
            getShowname().setDirty(false);
            nbt.putBoolean("showname", getShowname().getValue());
        }
        if (getSortCount().isDirty()) {
            getSortCount().setDirty(false);
            nbt.putInt("SortCount", getSortCount().getValue());
        }
    }

    @Override
    public void readDrityCustomDataFromNbt(NbtCompound nbt) {
        for (String s : nbt.getKeys()) {
            if (s.equals("name")) {
                setName(Text.Serializer.fromJson(nbt.getString("name")));
                continue;
            }
            if (s.equals("showname")) {
                setShowname(nbt.getBoolean("showname"));
                continue;
            }
            if (s.equals("SortCount")) {
                setSortCount(nbt.getInt("SortCount"));
                continue;
            }
            UUID num = UUID.fromString(s);
            CustomBossBarColumn column = getBossColumn(num);
            if (column != null) {
                column.readDrityCustomDataFromNbt(nbt.getCompound(s));
            }
        }
    }

    @Override
    public void writeCustomDataToNbt(NbtCompound nbt) {
        for (int i = 0; i < getBossColumn().size(); i++) {
            NbtCompound nbtCompound = new NbtCompound();
            getBossColumn().get(i).writeCustomDataToNbt(nbtCompound);
            nbt.put(getBossColumn().get(i).getUuid().getValue().toString(), nbtCompound);
        }
        if (name.getValue() != null) {
            nbt.putString("name", Text.Serializer.toJson(getName().getValue()));
        }
        nbt.putBoolean("showname", getShowname().getValue());
        nbt.putInt("SortCount", getSortCount().getValue());
    }

    @Override
    public void tick(MobEntity mobEntity) {
        for (CustomBossBarColumn customBossBarColumn : getBossColumn()) {
            customBossBarColumn.tick(mobEntity);
            if (customBossBarColumn.getDrity() && !getDrity()) {
                setDrity(true);
            }
        }
    }

    @Override
    @Nullable
    public CustomBossBar getBossBar(Text name) {
        CustomBossBar bossBar = null;
        for (CustomBossBarColumn customBossBarColumn : getBossColumn()) {
            bossBar = customBossBarColumn.getBossBar(name);
            if (bossBar != null) break;
        }
        return bossBar;
    }

    @Override
    @Nullable
    public CustomBossBar getBossBar(UUID uuid) {
        CustomBossBar bossBar = null;
        for (CustomBossBarColumn customBossBarColumn : getBossColumn()) {
            bossBar = customBossBarColumn.getBossBar(uuid);
            if (bossBar != null) break;
        }
        return bossBar;
    }

    @Override
    public void addBossColumn(CustomBossBarColumn customBossBarColumn) {
        bossColumns.add(customBossBarColumn);
        setDrity(true);
    }

    @Override
    @Nullable
    public CustomBossBarColumn getBossColumn(Text name) {
        for (CustomBossBarColumn customBossBarColumn : getBossColumn()) {
            if (customBossBarColumn.getName().getValue().equals(name)) {
                return customBossBarColumn;
            }
        }
        return null;
    }

    @Override
    @Nullable
    public CustomBossBarColumn getBossColumn(UUID uuid) {
        for (CustomBossBarColumn customBossBarColumn : getBossColumn()) {
            if (customBossBarColumn.getUuid().getValue().equals(uuid)) {
                return customBossBarColumn;
            }
        }
        return null;
    }

    @Override
    public CopyOnWriteArrayList<CustomBossBarColumn> getBossColumn() {
        return bossColumns;
    }

    @Override
    public void setBossColumns(CopyOnWriteArrayList<CustomBossBarColumn> bossBars) {
        this.bossColumns = bossBars;
    }

    @Override
    public boolean getDrity() {
        return drity;
    }

    @Override
    public void setDrity(boolean drity) {
        this.drity = drity;
    }

    @Override
    public DataTracking<Text> getName() {
        return name;
    }

    @Override
    public void setName(Text name) {
        this.name.setValue(name);
        if (this.name.isDirty()) setDrity(true);
    }

    @Override
    public DataTracking<Boolean> getShowname() {
        return showname;
    }

    @Override
    public void setShowname(boolean showname) {
        this.showname.setValue(showname);
        if (this.showname.isDirty()) setDrity(true);
    }

    @Override
    public DataTracking<Integer> getSortCount() {
        return SortCount;
    }

    @Override
    public void setSortCount(int count) {
        this.SortCount.setValue(count);
        if (this.SortCount.isDirty()) setDrity(true);
    }
}
